<template>
  <div ref="chartEl"></div>
</template>
<script lang="ts" setup>
import { use, init, EChartsType } from "echarts/core";
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  LegendComponentOption,
  ToolboxComponent,
  DataZoomComponent,
  RadarComponent,
} from "echarts/components";
import { BarChart, PieChart, LineChart, SankeyChart, RadarChart } from "echarts/charts";
import { GraphicComponent } from "echarts/components";
import { LabelLayout } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import type { DefaultSeriesOption, EChartsOption, SeriesOption } from "./models";
import { shallowRef, onMounted, watch, onBeforeUnmount } from "vue";
import { colors } from "/@/style/style";
import { deepMergeObj } from "/@/utils/common";
import ResizeObserver from "resize-observer-polyfill";
import { useHomeStore } from "/@/stores/home";
import type { YAXisOption } from "echarts/types/dist/shared";

const props = defineProps<{
  option?: EChartsOption;
}>();

use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  BarChart,
  PieChart,
  LabelLayout,
  CanvasRenderer,
  LineChart,
  GraphicComponent,
  SankeyChart,
  ToolboxComponent,
  DataZoomComponent,
  RadarComponent,
  RadarChart,
]);

const emits = defineEmits(["clickEvent"]);
const chartEl = shallowRef<HTMLDivElement>();
const homeStore = useHomeStore();

const defaultSeriesOption: DefaultSeriesOption = {
  bar: {
    barMaxWidth: 30,
  },
};
function handleSeries(option?: SeriesOption): SeriesOption | null {
  if (option && option.type) {
    const target = defaultSeriesOption[option.type];
    return Object.assign(
      {
        zlevel: 1,
        z: 1,
      },
      target || {},
      option
    );
  }
  return null;
}
function handleDefaultAxis(axis: EChartsOption["xAxis"] | EChartsOption["yAxis"]) {
  if (axis) {
    (Array.isArray(axis) ? axis : [axis]).forEach((item) => {
      const defaultItem: typeof item = {
        axisLabel: {
          color: "#172B4D",
        },
        axisLine: {
          lineStyle: {
            color: "#E1E2E6",
          },
        },
      };
      deepMergeObj(item, defaultItem);
    });
  }
}
function handleOption(option: EChartsOption) {
  const defaultOption: EChartsOption = {
    legend: {
      textStyle: {},
    },
    grid: {
      left: 16,
      right: 16,
      bottom: 16,
      top: 16,
      containLabel: true,
      borderColor: "#E1E2E6",
    },
    color: [colors.primary, colors.green],
  };
  deepMergeObj(defaultOption, option);
  handleDefaultAxis(defaultOption.xAxis);
  handleDefaultAxis(defaultOption.yAxis);
  //处理series默认配置
  if (defaultOption.series) {
    if (Array.isArray(defaultOption.series)) {
      defaultOption.series.forEach((el, i, arr) => {
        const re = handleSeries(el);
        if (re) {
          arr[i] = re;
        }
      });
    } else {
      const re = handleSeries(defaultOption.series);
      if (re) {
        defaultOption.series = re;
      }
    }
  }
  if (homeStore.darkMode === "dark") {
    const legend = defaultOption.legend as LegendComponentOption;
    if (legend && legend.textStyle) {
      legend.textStyle.color = "#ffffff";
    }
  }

  return defaultOption;
}

watch(
  () => homeStore.darkMode,
  (v) => {
    if (chartEl.value && props.option && chartIns) {
      chartIns.dispose();
      chartIns = init(chartEl.value, v);
      const option = handleOption(props.option);
      chartIns.setOption(option);
    }
  }
);

let chartIns: EChartsType | null = null;
let resizeObserver: ResizeObserver | null;
onMounted(() => {
  if (chartEl.value && props.option) {
    chartIns = init(chartEl.value, homeStore.darkMode);
    const option = handleOption(props.option);
    chartIns.setOption(option);
    chartIns.getZr().on("click", function (param) {
      // 获取 点击的 触发点像素坐标
      const pointInPixel = [param.offsetX, param.offsetY];
      // 判断给定的点是否在指定的坐标系或者系列上
      if (chartIns?.containPixel("grid", pointInPixel)) {
        // 获取到点击的 x轴 下标  转换为逻辑坐标
        // const xIndex = chartIns?.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
        const xIndex = chartIns?.convertFromPixel({ seriesIndex: 0 }, pointInPixel)[1];
        // 获取当前点击位置要的数据
        let op: any = chartIns.getOption();
        let par = op?.series[0]?.data[xIndex];
        emits("clickEvent", { data: par });
      }
    });
    // 修改样式 移入图换成小手
    chartIns.getZr().on("mousemove", function (params) {
      const pointInPixel = [params.offsetX, params.offsetY];
      if (chartIns?.containPixel("grid", pointInPixel)) {
        chartIns.getZr().setCursorStyle("pointer");
      }
    });
    // 这种方法只能点击图才能触发
    // chartIns.on("click", (parmas) => {
    //   console.info("parmas==>", parmas);
    //   // emits("clickEvent", parmas);
    // });
  }

  if (chartEl.value) {
    const containerEl = chartEl.value;
    //实现自适应div container的大小
    resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
      const entry = entries[0];
      // console.log("========>ResizeObserver resize");
      if (entry && chartIns) {
        chartIns.resize();
      }
    });
    resizeObserver.observe(containerEl);
  }
});
onBeforeUnmount(() => {
  if (resizeObserver) {
    console.log("=======>ResizeObserver unmount");
    resizeObserver.disconnect();
    resizeObserver = null;
  }
});
watch(
  () => props.option,
  (v) => {
    if (chartIns && v) {
      const option = handleOption(v);
      chartIns.setOption(option);
    } else {
      chartIns = null;
    }
  }
);
</script>
